Summary of Behavior
When you create an
Optionalfrom a mutable or immutable object, theOptionalholds a reference to that object in memory. Reassigning the original local variable tonulldoes not affect the value stored inside theOptional.
Code Example
public class App {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("test");
Optional<StringBuilder> sOp = Optional.of(sb);
sb = null; // Reassigns local variable, but sOp is untouched
if (sOp.isPresent()) {
System.out.println("sOp is not null"); // Prints this
} else {
System.out.println("sOp is null");
}
sOp.ifPresent(System.out::println); // Prints "test"
}
}
Output
sOp is not null test
Modern Ways to Handle Optional in JDK 21
Since you are using JDK 21, you have access to clean, expressive patterns to process and display Optional values without messy if-else blocks.
1. Using Stream API (Optional.stream())
Since Java 9 (and fully supported in JDK 21), Optional provides a .stream() method. This allows you to treat an Optional as a Stream of 0 or 1 element, making it easy to chain with other stream operations like .map() or .filter().
import java.util.Optional;
public class StreamExample {
public static void main(String[] args) {
Optional<StringBuilder> sOp = Optional.of(new StringBuilder("test"));
sOp.stream()
.map(StringBuilder::toString)
.map(String::toUpperCase)
.forEach(System.out::println); // Prints: TEST
}
}
Why use
.stream()? It is extremely useful when you want to combine multipleOptionalobjects or filter them inside a larger stream pipeline without unpacking them manually.
2. Pattern Matching for switch (JDK 21 Feature Preview/Finalized)
While Optional doesn’t directly pattern-match in a switch expression out of the box, you can combine modern Java features or use newer functional idioms available in JDK 21.
However, for standard conditional checks, modern functional methods on Optional remain the cleanest approach:
// Executes only if present, otherwise runs the alternative
sOp.ifPresentOrElse(
val -> System.out.println("Found: " + val),
() -> System.out.println("Value is missing")
);
3. Transforming and Filtering (map and filter)
If you want to conditionally process the contents only if they meet a condition:
sOp.filter(val -> val.length() > 2)
.ifPresent(val -> System.out.println("Valid length: " + val));
Best Practice with
OptionalAvoid usingOptional.get()or checkingisPresent()followed byget(). Instead, prefer functional methods likeifPresent,map,orElse, orifPresentOrElseto write safer, more idiomatic Java code.